package com.tarena.lbs.basic.web.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.base.protocol.pager.BasePageList;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.mq.NoticeProducer;
import com.tarena.lbs.basic.web.repository.StoreChainRepository;
import com.tarena.lbs.basic.web.repository.StoreRepository;
import com.tarena.lbs.basic.web.service.IEsService;
import com.tarena.lbs.basic.web.service.IStoreService;
import com.tarena.lbs.common.attach.enums.BusinessTypeEnum;
import com.tarena.lbs.common.basic.constance.Const;
import com.tarena.lbs.common.basic.converter.StoreConverter;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.pojo.attach.dto.AttachDTO;
import com.tarena.lbs.pojo.attach.dto.AttachQrDTO;
import com.tarena.lbs.pojo.attach.param.AttachQRParam;
import com.tarena.lbs.pojo.attach.param.AttachUpdateParam;
import com.tarena.lbs.pojo.attach.query.AttachQuery;
import com.tarena.lbs.pojo.basic.bo.StoreBO;
import com.tarena.lbs.pojo.basic.dos.PictureDO;
import com.tarena.lbs.pojo.basic.dos.StoreChainDO;
import com.tarena.lbs.pojo.basic.dos.StoreDO;
import com.tarena.lbs.pojo.basic.param.EsUpdateParam;
import com.tarena.lbs.pojo.basic.param.StoreParam;
import com.tarena.lbs.pojo.basic.param.UserLocationParam;
import com.tarena.lbs.pojo.basic.param.UserStoreParam;
import com.tarena.lbs.pojo.basic.query.AreaStoreQuery;
import com.tarena.lbs.pojo.basic.query.EsQuery;
import com.tarena.lbs.pojo.basic.query.MarketingSelectedQuery;
import com.tarena.lbs.pojo.basic.query.StoreQuery;
import com.tarena.lbs.pojo.basic.query.UserStoreQuery;
import com.tarena.lbs.pojo.basic.vo.PictureVO;
import com.tarena.lbs.pojo.basic.vo.StoreVO;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Service
@Slf4j
public class StoreServiceImpl implements IStoreService {

    private static final String STORE_LINK = "https://store.example.com/store?store=store";

    @Autowired
    StoreRepository storeRepository;

    @Autowired
    StoreConverter storeConverter;

    @Autowired
    StoreChainRepository storeChainRepository;

    @Resource
    AttachApi attachApi;

    @Resource
    private IEsService iEsService;

    @Autowired
    private NoticeProducer noticeProducer;

    @Value("${app.attach.url}")
    private String url;

    @Override
    @Transactional
    public void shopAdd(StoreParam storeParam) {
        //插入店铺
        StoreDO storeDO = storeConverter.param2DO(storeParam);
        int id = storeRepository.shopAdd(storeDO);

        //插入二维码
        String replace = UUID.randomUUID().toString().replace("-", "");
        String content = STORE_LINK + replace;
        AttachQRParam param = new AttachQRParam(content, BusinessTypeEnum.SHOP_QR.getType(), id);
        AttachQrDTO dto = attachApi.generateQrCode(param);
        String url = dto.getUrl();
        StoreChainDO storeChainDO = new StoreChainDO(id, content, url, 0, LocalDateTime.now());
        storeChainRepository.insert(storeChainDO);

        //数据插入es
        EsUpdateParam esUpdateParam = new EsUpdateParam(storeDO.getId(), Const.CONTENT_INDEX_DATABASE_NAME);
        GeoPoint geoPoint = new GeoPoint(Double.valueOf(storeParam.getLatitude()),Double.valueOf(storeParam.getLongitude()));
        storeDO.setLocation(geoPoint);
        iEsService.insertData(esUpdateParam,storeDO);

        //更新附件
        createAttach(id,BusinessTypeEnum.STORE.getType(),storeParam.getStoreImagesIds());
        createAttach(id,BusinessTypeEnum.SHOP_LOGO.getType(), Arrays.asList(storeParam.getStoreLogo()));
    }

    private void createAttach(Integer businessId,Integer businessType,List<String> fileIds) {
        List<AttachUpdateParam> attachUpdateParams = new ArrayList<>();
        fileIds.forEach(id -> {
            AttachUpdateParam updateParam = new AttachUpdateParam();
            updateParam.setId(Integer.valueOf(id));
            updateParam.setBusinessId(businessId);
            updateParam.setBusinessType(businessType);
            updateParam.setIsCover(0);
            attachUpdateParams.add(updateParam);
        });
        attachApi.batchUpdateAttachByIdList(attachUpdateParams);
    }

    @Override
    public void deleteByID(Integer id) {
        //todo:查询门店是否存在
        //todo:如果门店不存在则异常处理
        int row = storeRepository.deleteByID(id);
        //todo:如果删除失败则异常处理
    }

    @Override
    public void enableStatusById(Integer id) {
        //todo:查询门店是否存在
        //todo:如果门店不存在则异常处理
        int row = storeRepository.enableStatusById(id);
        //todo:如果启用失败则异常处理
    }

    @Override
    public void disableStatusById(Integer id) {
        //todo:查询门店是否存在
        //todo:如果门店不存在则异常处理
        int row = storeRepository.disableStatusById(id);
        //todo:如果禁用失败则异常处理
    }

    @Override
    public PageResult<StoreVO> getAll(StoreQuery storeQuery) {
        int pageSize = storeQuery.getPageSize();
        int pageNum = storeQuery.getPageNo();
        //new PageQuery(pageNum, pageSize);
        List<StoreDO> storeDoList = storeRepository.selectAll(storeQuery);
        PageInfo<StoreDO> pageInfo = new PageInfo<>(storeDoList);
        List<StoreVO> storeVOList = pageInfo.getList().stream().map(storeDO -> {
            StoreVO storeVO = new StoreVO();
            if (storeDO != null) {
                BeanUtils.copyProperties(storeDO, storeVO);
            }
            return storeVO;
        }).collect(Collectors.toList());
        PageResult<StoreVO> pageResult = new PageResult<>();
        pageResult.setObjects(storeVOList);
        pageResult.setTotal(pageInfo.getTotal());
        pageResult.setPageNo(pageNum);
        pageResult.setPageSize(pageSize);
        return pageResult;
    }

    public List<PictureVO> getPictureByStore(StoreDO storeDO, List<PictureDO> pictureDoList) {
        String[] ids = storeDO.getStoreImagesId().split(",");
        ArrayList<PictureVO> pictureVOS = new ArrayList<>();
        PictureVO pictureVO = new PictureVO();
        for (String id : ids) {
            for (PictureDO pictureDO : pictureDoList) {
                if (pictureDO.getId().toString().equals(id)) {
                    BeanUtils.copyProperties(pictureDO, pictureVO);
                    pictureVOS.add(pictureVO);
                }
            }
        }

        return pictureVOS;
    }

    @Override
    public StoreVO getStoreById(Integer id) {
        StoreDO storeDO = storeRepository.getStoreById(id);
        if (storeDO != null) {
            StoreVO storeVO = storeConverter.doo2vo(storeDO);
            AttachQuery attachQuery = new AttachQuery();
            attachQuery.setBusinessType(BusinessTypeEnum.STORE.getType());
            attachQuery.setBusinessId(id);
            List<AttachDTO> attachInfo = attachApi.getAttachInfoByParam(attachQuery);
            List<PictureVO> pictureVOList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(attachInfo)) {
                for (AttachDTO attachDTO : attachInfo) {
                    PictureVO pictureVO = new PictureVO();
                    pictureVO.setId(attachDTO.getId());
                    pictureVO.setImage(url + attachDTO.getFileUuid());
                    pictureVOList.add(pictureVO);
                }
            }
            storeVO.setPictureVOS(pictureVOList);
            AttachQuery logoAttachQuery = new AttachQuery();
            logoAttachQuery.setBusinessType(BusinessTypeEnum.SHOP_LOGO.getType());
            logoAttachQuery.setBusinessId(id);
            List<AttachDTO> logoAttachInfo = attachApi.getAttachInfoByParam(logoAttachQuery);
            if (!CollectionUtils.isEmpty(logoAttachInfo)) {
                storeVO.setStoreLogo(url + logoAttachInfo.get(0).getFileUuid());
            }

            return storeVO;
        }
        return null;

    }

    @Override
    public void updateStore(StoreParam storeParam) {
        StoreDO storeDO = storeRepository.getStoreById(storeParam.getId());
//        if (store==null){
//            throw new StoreGlobalExceptionHandler()
//        }
        storeDO.setUpdateTime(new Date());
        int row = storeRepository.updateByPrimaryKeySelective(storeDO);

    }

    @Override
    public void userLocation(UserLocationParam param) throws Exception {
        EsQuery query = new EsQuery();
        query.setIndexName(Const.CONTENT_INDEX_DATABASE_NAME);
        query.setFrom(0);
        query.setSize(10);
        SearchResponse response = iEsService.searchGeo(query, Double.valueOf(param.getLatitude()), Double.valueOf(param.getLongitude()));
        //只找距离最近的店铺
        StoreDO store = null;
        if (response.getHits().getHits().length > 0) {
            SearchHit hit = response.getHits().getHits()[0];
            store = JSONObject.parseObject(hit.getSourceAsString(), StoreDO.class);
            log.info("进入范围，店铺信息为{}",JSONObject.toJSONString(store));
        }
        //调用mq发券
        if (store != null) {
            UserPrinciple loginUser = LbsSecurityContenxt.getLoginToken();
            if (loginUser != null) {
                UserStoreParam userStoreParam = new UserStoreParam(loginUser.getId(), store.getId());
                noticeProducer.sendMsg(JSONObject.toJSONString(userStoreParam));
            }
        }
    }

    @Override
    public void userInterest(UserStoreParam userStoreParam) throws Exception {
        EsUpdateParam param = new EsUpdateParam(null,Const.INTEREST_INDEX_DATABASE_NAME);
        StoreVO storeVO = getStoreById(userStoreParam.getStoreId());
        storeVO.setUserId(userStoreParam.getUserId());
        iEsService.insertData(param,storeVO);
    }

    @Override
    public PageResult<StoreVO> userInterestStoreList(UserStoreQuery userStoreQuery) throws Exception {
        UserPrinciple loginUser = LbsSecurityContenxt.getLoginToken();
        if (loginUser != null) {
            userStoreQuery.setUserId(loginUser.getId());
        }
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.from(userStoreQuery.getPageNo());
        builder.size(userStoreQuery.getPageSize());
        builder.query(QueryBuilders.termQuery("userId",userStoreQuery.getUserId()));
        List<StoreVO> storeVOList = new ArrayList<>();
        SearchResponse response = iEsService.search(Const.INTEREST_INDEX_DATABASE_NAME,builder);
        for (int i = 0; i < response.getHits().getHits().length; i++) {
            SearchHit hit = response.getHits().getHits()[i];
            StoreVO storeVO = JSONObject.parseObject(hit.getSourceAsString(), StoreVO.class);
            log.info("-----" + JSONObject.toJSONString(storeVO));
            storeVOList.add(storeVO);
        }
        PageResult<StoreVO> pageResult = new PageResult<>();
        pageResult.setObjects(storeVOList);
        pageResult.setPageNo(userStoreQuery.getPageNo());
        pageResult.setPageSize(userStoreQuery.getPageSize());
        pageResult.setTotal(Long.valueOf(storeVOList.size()));
        return pageResult;
    }

    /**
     * 功能描述: 查询城市下的区域
     *
     * @param storeQuery
     */
    @Override
    public BasePageList<StoreBO> getStoreByCity(AreaStoreQuery storeQuery) {
        return storeRepository.getStoreByCity(storeQuery);
    }

    /**
     * 功能描述：获取活动选中的店铺
     *
     * @param storeQuery
     */
    @Override
    public BasePageList<StoreBO> marketingStoreList(MarketingSelectedQuery storeQuery) {
        return storeRepository.marketingStoreList(storeQuery);
    }
}
